package com.ecar.api.rest.pay;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

import net.sf.json.JSONObject;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

import com.ecar.api.pay.ali.AlipayConfig;
import com.ecar.api.pay.ali.AlipayNotify;
import com.ecar.api.pay.wx.AdvancedUtil;
import com.ecar.api.pay.wx.SNSUserInfo;
import com.ecar.api.pay.wx.TimeUtil;
import com.ecar.api.pay.wx.WechatUtils;
import com.ecar.api.pay.wx.WeixinOauth2Token;
import com.ecar.api.pay.wx.WeixinPay;
import com.ecar.api.pay.wx.WeixinPayConfig;
import com.ecar.api.pay.wx.WxPayData;
import com.ecar.api.pay.wx.WxPayUtil;
import com.ecar.api.rest.AbstractResource;
import com.ecar.api.service.common.ActivityService;
import com.ecar.api.service.order.OrderService;
import com.ecar.api.service.pay.PayService;
import com.ecar.api.service.pay.impl.PayServiceImpl;
import com.ecar.api.support.dto.Constants;
import com.ecar.api.support.util.Redis;
import com.ecar.api.support.util.WechatXMLParser;
import com.ecar.common.annotation.ResponseFilter;
import com.ecar.common.dto.DataBean;
import com.ecar.common.util.HttpUtils;
import com.ecar.core.common.entity.Coupon;
import com.ecar.core.common.entity.CouponActivities;
import com.ecar.core.order.entity.Order;
import com.ecar.core.order.entity.Payment;

/**
 * 支付接口
 * 
 * @author zcw 2017-10-26 
 */
@Controller
@Scope("prototype")
@Path("/pay")
public class PayController extends AbstractResource{
	
	private static Logger log = LoggerFactory.getLogger(PayController.class);
	
	@Context
	HttpServletRequest request;

	@Context
	HttpServletResponse response;
	
	@Autowired
	private PayService payService;
	
	@Autowired
	private OrderService orderService;
	
	@Autowired
	private ActivityService activityService;
	/**
	 * 获取支付接口签名  支付宝
	 * @param orderId
	 * @return
	 */
	@POST
	@Path("/ali")
	@Produces(MediaType.APPLICATION_JSON)
	public DataBean alipay(JSONObject param) {
		try {
			if (!parse(param) || this.fields == null) return new DataBean(400, "","请求参数格式错误！");
			String orderIdStr = this.fields.getString("orderId");
			log.info("调取支付宝接口:订单号为"+orderIdStr);
			String orderId = orderIdStr;
			if (orderId.equals(null)) return new DataBean(400, "","参数错误。");
			
			Order order=orderService.selectByOrderNum(orderId);
			if(order==null){
				return new DataBean(400, "","未找到相关支付订单！");
			}
			if(order.getPayStatus()==Order.ST.PAID.val()){
				return new DataBean(666, "","此订单已支付，请不要做重复支付操作！");
			}
			String couponActivityId = this.fields.getString("couponActivityId");
			if(this.fields.has("couponActivityId")){//前端传入优惠卷活动ID
				if(couponActivityId!=null && !couponActivityId.trim().equals("")){//前端传入优惠卷活动ID
					
					//对支付使用的优惠卷做处理
					Coupon coupon=activityService.selectByCouponActIdAndUserId(this.fields.getString("couponActivityId"), order.getPassengerId()+"");
					if(coupon==null){
						return new DataBean(400, "","未获取到此优惠卷信息！");
					}
					if(coupon.getStatus()==2 || coupon.getStatus()==3){
						return new DataBean(400, "","您的优惠卷已使用或已过使用期！");
					}
//					coupon.setStatus(Coupon.BEAN_USED);
//					int as=activityService.updateByPrimaryKey(coupon);
//					if(as<=0){
//						return new DataBean(400, new JSONObject(),"使用优惠卷失败！");
//					}
					CouponActivities couponActivities=activityService.selectByPrimaryKey(couponActivityId);
					order.setCouponId(coupon.getId());
					order.setDeductionPrice(couponActivities.getCouponPrice());
					order.setActualPrice(order.getOrderPrice()-couponActivities.getCouponPrice());
					int ordNum=orderService.updateByPrimaryKeySelective(order);
					if(ordNum<=0){
						return new DataBean(400, "","使用优惠卷使用异常，数据库错误！");
					}
				}
				
			}
			
			return payService.setAlipaySign(orderId,couponActivityId);
		} catch (Exception e) {
			e.printStackTrace();
			return new DataBean(500, "","支付异常！");
		}
	}
	
	/**
	 * 该页面调试工具请使用写文本函数logResult，该函数在com.alipay.util文件夹的AlipayNotify.java类文件中
	 * 如果没有收到该页面返回的 success 信息，支付宝会在24小时内按一定的时间策略重发通知
	 * 支付回调接口 支付宝
	 * @return
	 */
	@POST
	@Path("/ali/notify")
	public void alipayNotify() {
		//获取支付宝POST过来反馈信息
		Map<String, String> params = new HashMap<>();
		Map requestParams = request.getParameterMap();
		Iterator iter = requestParams.keySet().iterator();
		String s = "";
		while (iter.hasNext()) {
			//		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i]
						: valueStr + values[i] + ",";
			}
			s += valueStr;
			//乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
			params.put(name, valueStr);
		}
		log.info("收到支付宝异步回调：");  
	    log.info(request.getParameterMap().toString());  
		log.info("支付宝支付通知: " + s);
		PrintWriter out;
		try {
			out = response.getWriter();
			//获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
			//商户订单号
			String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");

			//支付宝交易号
			String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");

			//交易状态
			String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");

			//获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
			if (AlipayNotify.verify(params)) {//验证成功
				//////////////////////////////////////////////////////////////////////////////////////////
				//请在这里加上商户的业务逻辑程序代码
				//noinspection StatementWithEmptyBody
				if (trade_status.equals("TRADE_FINISHED")) {
					//判断该笔订单是否在商户网站中已经做过处理
					//如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
					//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
					//如果有做过处理，不执行商户的业务程序
						
					//注意：
					//退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
				} else if (trade_status.equals("TRADE_SUCCESS")) {
					//判断该笔订单是否在商户网站中已经做过处理
					//如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
					//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
					//如果有做过处理，不执行商户的业务程序

					//交易金额
					log.info("支付宝支付成功。");
					String total_fee = new String(request.getParameter("total_fee").getBytes("ISO-8859-1"), "UTF-8");
					String dateStr = new String(request.getParameter("gmt_payment").getBytes("ISO-8859-1"), "UTF-8");
					payService.checkPayment(out_trade_no, total_fee, trade_no,dateStr,Constants.TYPE_ALIPAY);
					//注意：
					//付款完成后，支付宝系统发送该交易状态通知
				}
				out.println("success");    //请不要修改或删除
			} else {
				log.info("支付宝支付信息验证失败。");
				out.println("fail");
			}
		} catch (IOException e) {
			log.error(e.getMessage());
		}
	}
	
	/**
	 * 统一下单，生成支付签名    APP下单使用
	 * 统一下单 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
	 * 调起支付 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12&index=2
	 * @param orderId
	 * @return
	 */
	@POST
	@Path("/wx/app")
	@Produces(MediaType.APPLICATION_JSON)
	public DataBean wxpay(JSONObject param) {
		try {
			if (!parse(param) || this.fields == null) return new DataBean(400, new JSONObject(),"请求参数格式错误！");
			String orderIdStr = this.fields.getString("orderId");
			log.info("调取微信支付接口:订单号为"+orderIdStr);
			String orderId = orderIdStr;
			if (orderId.equals(null)) return new DataBean(400, new JSONObject(),"参数错误。");
			Order order=orderService.selectByOrderNum(orderId);
			if(order==null){
				return new DataBean(400, new JSONObject(),"未找到相关支付订单！");
			}
			if(order.getPayStatus()==Order.ST.PAID.val()){
				return new DataBean(666, new JSONObject(),"此订单已支付，请不要做重复支付操作！");
			}
			String couponActivityId = this.fields.getString("couponActivityId");
			if(this.fields.has("couponActivityId")){//前端传入优惠卷活动ID
				if(couponActivityId!=null && !couponActivityId.trim().equals("")){//前端传入优惠卷活动ID
					
					//对支付使用的优惠卷做处理
					Coupon coupon=activityService.selectByCouponActIdAndUserId(this.fields.getString("couponActivityId"), order.getPassengerId()+"");
					if(coupon==null){
						return new DataBean(400, new JSONObject(),"未获取到此优惠卷信息！");
					}
					if(coupon.getStatus()==2 || coupon.getStatus()==3){
						return new DataBean(400, new JSONObject(),"您的优惠卷已使用或已过使用期！");
					}
					//支付后更新
//					coupon.setStatus(Coupon.BEAN_USED);
//					int as=activityService.updateByPrimaryKey(coupon);
//					if(as<=0){
//						return new DataBean(400, new JSONObject(),"使用优惠卷失败！");
//					}
					CouponActivities couponActivities=activityService.selectByPrimaryKey(couponActivityId);
					order.setCouponId(coupon.getId());
					order.setDeductionPrice(couponActivities.getCouponPrice());
					order.setActualPrice(order.getOrderPrice()-couponActivities.getCouponPrice());
					int ordNum=orderService.updateByPrimaryKeySelective(order);
					if(ordNum<=0){
						return new DataBean(400, new JSONObject(),"使用优惠卷使用异常，数据库错误！");
					}
				}
				
			}
//			String ip="192.168.31.127";//测试ip
			String ip = HttpUtils.getRemoteHost(request);
			return payService.setWxAppPaySign(orderId, ip,couponActivityId);//不能活动ipv6地址
		} catch (Exception e) {
			e.printStackTrace();
			return new DataBean(500,new JSONObject(),"支付异常！");
		}
	}
	
	/**
	 * 统一下单，生成支付签名    h5下单使用
	 * 统一下单 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
	 * 调起支付 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12&index=2
	 * @param orderId
	 * @return
	 */
	@POST
	@Path("/wx/h5")
	@Produces(MediaType.APPLICATION_JSON)
	public DataBean wxh5pay(JSONObject param) {
		try {
			if (!parse(param) || this.fields == null) return new DataBean(400, new JSONObject(),"请求参数格式错误！");
			String orderIdStr = this.fields.getString("orderId");
			log.info("调取微信支付接口:订单号为"+orderIdStr);
			String orderId = orderIdStr;
			if (orderId.equals(null)) return new DataBean(400, new JSONObject(),"参数错误。");
			Order order=orderService.selectByOrderNum(orderId);
			if(order==null){
				return new DataBean(400, new JSONObject(),"未找到相关支付订单！");
			}
			if(order.getPayStatus()==Order.ST.PAID.val()){
				return new DataBean(666, new JSONObject(),"此订单已支付，请不要做重复支付操作！");
			}
			String couponActivityId = null;
			if(this.fields.has("couponActivityId")){//前端传入优惠卷活动ID
				couponActivityId = this.fields.getString("couponActivityId");
				if(couponActivityId!=null && !couponActivityId.trim().equals("")){//前端传入优惠卷活动ID
					
					//对支付使用的优惠卷做处理
					Coupon coupon=activityService.selectByCouponActIdAndUserId(this.fields.getString("couponActivityId"), order.getPassengerId()+"");
					if(coupon==null){
						return new DataBean(400, new JSONObject(),"未获取到此优惠卷信息！");
					}
					if(coupon.getStatus()==2 || coupon.getStatus()==3){
						return new DataBean(400, new JSONObject(),"您的优惠卷已使用或已过使用期！");
					}
					CouponActivities couponActivities=activityService.selectByPrimaryKey(couponActivityId);
					order.setCouponId(coupon.getId());
					order.setDeductionPrice(couponActivities.getCouponPrice());
					order.setActualPrice(order.getOrderPrice()-couponActivities.getCouponPrice());
					int ordNum=orderService.updateByPrimaryKeySelective(order);
					if(ordNum<=0){
						return new DataBean(400, new JSONObject(),"使用优惠卷使用异常，数据库错误！");
					}
				}
				
			}
//			String ip="192.168.31.127";//测试ip
			String ip = HttpUtils.getRemoteHost(request);
			boolean flag=false;
			//调取微信h5支付的
			if(flag){
				order.setPayStatus(2);
				order.setCouponId("");
				order.setDeductionPrice(0);
				order.setActualPrice(order.getOrderPrice()-0);
				int i=orderService.updateByOrderNumSelective(order);
				if(i<=0){
					return new DataBean(200,new JSONObject(),"支付成功");
				}
				return new DataBean(500,new JSONObject(),"支付失败,写入数据库失败");
			}
			return new DataBean(500,new JSONObject(),"支付失败");
			
		} catch (Exception e) {
			e.printStackTrace();
			return new DataBean(500,new JSONObject(),"支付异常！");
		}
	}
	
	/**
	 * 同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
	 * 特别提醒：商户系统对于支付结果通知的内容一定要做签名验证，防止数据泄漏导致出现“假通知”，造成资金损失。
	 * 支付结果通用通知
	 * @return
	 */
	@POST
	@Path("/wx/notify")
	public void wxpayNotify() {
		//获取微信 POST过来反馈信息
		String line;
		StringBuilder sb = new StringBuilder();
		PrintWriter out;
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}

			log.info("微信APP支付通知: " + sb.toString());
			response.setContentType("text/xml;charset=utf-8");
			out = response.getWriter();

			//验证签名
			if (WeixinPay.checkIsSignValidFromResponseString(sb.toString())) {//验证成功
				Map<String, String> requestMap = WechatXMLParser.parseString(sb.toString());
				if ("SUCCESS".equals(requestMap.get("return_code"))) {
					//请加入业务逻辑代码
					if ("SUCCESS".equals(requestMap.get("result_code"))) {
						////请加入业务逻辑代码
						/*交易类型 trade_type,付款银行 bank_type,总金额  total_fee,微信支付订单号 transaction_id
						详细参见  https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3
						 */
						log.info("微信APP支付成功。");
						String out_trade_no = requestMap.get("out_trade_no");
						String trade_no = requestMap.get("transaction_id");
						String total_fee = requestMap.get("total_fee");
						String time_end = requestMap.get("time_end");
						payService.checkPayment(out_trade_no, total_fee, trade_no,time_end,Constants.TYPE_WECHAT);
						out.println("<xml> <return_code><![CDATA[SUCCESS]]></return_code></xml>");    //请不要修改或删除
					} else {
						String err_code = requestMap.get("err_code");
						String err_code_des = requestMap.get("err_code_des");
						log.info("微信APP支付失败：【"+err_code+"】【"+err_code_des+"】");
					}
				} else {
					log.info("微信APP支付失败：" + requestMap.get("return_msg"));
					out.println(
							"<xml> <return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[返回结果为FAIL"
									+ "]]></return_msg></xml>");
				}
			} else {//验证失败
				log.info("微信APP支付信息验证失败。");
				out.println(
						"<xml> <return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg"
								+ "></xml>");
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage());
		}
	}
	
	/**
	 * 同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
	 * 特别提醒：商户系统对于支付结果通知的内容一定要做签名验证，防止数据泄漏导致出现“假通知”，造成资金损失。
	 * 支付结果通用通知
	 * @return
	 */
	@POST
	@Path("/wx/notify/h5")
	public void wxpayNotifyH5() {
		//获取微信 POST过来反馈信息
		String line;
		StringBuilder sb = new StringBuilder();
		PrintWriter out;
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}

			log.info("微信H5支付通知: " + sb.toString());
			response.setContentType("text/xml;charset=utf-8");
			out = response.getWriter();

			Map<String, String> requestMap = WechatXMLParser.parseString(sb.toString());
			if ("SUCCESS".equals(requestMap.get("return_code"))) {
				//请加入业务逻辑代码
				if ("SUCCESS".equals(requestMap.get("result_code"))) {
					////请加入业务逻辑代码
					/*交易类型 trade_type,付款银行 bank_type,总金额  total_fee,微信支付订单号 transaction_id
					 * 详细参见  https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3
					 */
					log.info("微信H5支付成功。");
					String out_trade_no = requestMap.get("out_trade_no");
					String trade_no = requestMap.get("transaction_id");
					String total_fee = requestMap.get("total_fee");
					String time_end = requestMap.get("time_end");
					payService.checkPayment(out_trade_no, total_fee, trade_no,time_end, Constants.TYPE_WECHATH5);
					out.println("<xml> <return_code><![CDATA[SUCCESS]]></return_code></xml>");    //请不要修改或删除
				} else {
					String err_code = requestMap.get("err_code");
					String err_code_des = requestMap.get("err_code_des");
					log.info("微信H5支付失败：【"+err_code+"】【"+err_code_des+"】");
				}
			} else {
				log.info("微信H5支付失败："+requestMap.get("return_msg"));
				out.println(
						"<xml> <return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[返回结果为FAIL"
								+ "]]></return_msg></xml>");
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage());
		}
	}

	/**
	 * 公众号  统一下单，返回预支付json
	 * https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=4_4
	 * 调起支付  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
	 * @param orderId
	 * @return
	 */
	/*@POST
	@Path("/wx/h5")
	@Produces(MediaType.APPLICATION_JSON)
	public DataBean getOrderInfoByJsAPI(JSONObject param) {
		try {
			if(!parse(param) || this.fields == null) return new DataBean(400,new JSONObject(), "请求参数格式错误！");
			log.info("订单号:{},token：{}" , this.fields.getString("orderNum") ,this.fields.getString("token"));
			return payService.setWxH5PaySign(this.fields.getString("orderNum"),this.fields.getString("token"));
		} catch (Exception e) {
			e.printStackTrace();
			return new DataBean(500, "支付异常！");
		}
	}*/
	
	/**
	 * 非微信内h5支付  统一下单，返回预支付json
	 * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
	 * 调起支付  https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
	 * @param orderId
	 * @return
	 */
	@GET
	@Path("/{orderNum}/notwx/h5")
	@Produces(MediaType.APPLICATION_JSON)
	public DataBean getOrderInfoOfH5ByJsAPI(@PathParam("orderNum") String orderNum) {
		try {
			if (StringUtils.isEmpty(orderNum)) return new DataBean(400, "参数错误。");
//			String ip="192.168.31.127";//测试ip
			String ip = HttpUtils.getRemoteHost(request);
			return payService.setNotWxH5PaySign(orderNum,ip,response);
			
		} catch (Exception e) {
			e.printStackTrace();
			return new DataBean(500, "支付异常！");
		}
	}
	
	/**
	 * 同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
	 * 特别提醒：商户系统对于支付结果通知的内容一定要做签名验证，防止数据泄漏导致出现“假通知”，造成资金损失。
	 * 支付结果通用通知
	 * @return
	 */
	@POST
	@Path("/notwx/notify/h5")
	public void notwxpayNotify() {
		//获取微信 POST过来反馈信息
		String line;
		StringBuilder sb = new StringBuilder();
		PrintWriter out;
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}

			log.info("微信APP支付通知: " + sb.toString());
			response.setContentType("text/xml;charset=utf-8");
			out = response.getWriter();

			//验证签名
			if (WeixinPay.checkIsSignValidFromResponseString(sb.toString())) {//验证成功
				Map<String, String> requestMap = WechatXMLParser.parseString(sb.toString());
				if ("SUCCESS".equals(requestMap.get("return_code"))) {
					//请加入业务逻辑代码
					if ("SUCCESS".equals(requestMap.get("result_code"))) {
						////请加入业务逻辑代码
						/*交易类型 trade_type,付款银行 bank_type,总金额  total_fee,微信支付订单号 transaction_id
						详细参见  https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3
						 */
						log.info("微信APP支付成功。");
						String out_trade_no = requestMap.get("out_trade_no");
						String trade_no = requestMap.get("transaction_id");
						String total_fee = requestMap.get("total_fee");
						String time_end = requestMap.get("time_end");
						payService.checkPayment(out_trade_no, total_fee, trade_no,time_end,Constants.TYPE_WECHAT);
						out.println("<xml> <return_code><![CDATA[SUCCESS]]></return_code></xml>");    //请不要修改或删除
					} else {
						String err_code = requestMap.get("err_code");
						String err_code_des = requestMap.get("err_code_des");
						log.info("微信APP支付失败：【"+err_code+"】【"+err_code_des+"】");
					}
				} else {
					log.info("微信APP支付失败：" + requestMap.get("return_msg"));
					out.println(
							"<xml> <return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[返回结果为FAIL"
									+ "]]></return_msg></xml>");
				}
			} else {//验证失败
				log.info("微信APP支付信息验证失败。");
				out.println(
						"<xml> <return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg"
								+ "></xml>");
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage());
		}
	}
	
	
	@GET
	@Path("/oautinfo")
	@Produces(MediaType.APPLICATION_JSON)
	public void oautinfo() throws ServletException, IOException {
		
		 request.setCharacterEncoding("utf-8");
	     response.setCharacterEncoding("utf-8");

	        // 用户同意授权后，能获取到code
	        String code = request.getParameter("code");
	        String state = request.getParameter("state");
	        System.out.println(code+"codecodecodecodecodecode");
	        // 用户同意授权
	        SNSUserInfo snsUserInfo  = null ;
	        if (!"authdeny".equals(code)) {
	            // 获取网页授权access_token
	            WeixinOauth2Token weixinOauth2Token = AdvancedUtil.getOauth2AccessToken(WxPayConstants.APPID, WxPayConstants.APP_SECRET, code);
	            // 网页授权接口访问凭证
	            String accessToken = weixinOauth2Token.getAccessToken();
	            // 用户标识
	            String openId = weixinOauth2Token.getOpenId();
	            // 获取用户信息
	             snsUserInfo = AdvancedUtil.getSNSUserInfo(accessToken, openId);

	            // 设置要传递的参数
	            request.setAttribute("snsUserInfo", snsUserInfo);
	            request.setAttribute("state", state);
	            
	            Redis.c.setnx(Redis.K.CODE.to(code),snsUserInfo.getOpenId() );
	            
	            response.sendRedirect(WeixinPayConfig.server_url+"?code="+code+"&openId="+openId+"&state=STATE#index");
	           // request.getRequestDispatcher("index.jsp").forward(request, response);
	           // return new DataBean(200, snsUserInfo, "查询成功返回车辆类型信息"); 
	        }
	        
	      //  return new DataBean(200, "已授权！！！", "查询成功返回车辆类型信息"); 
	       
	    //    request.getRequestDispatcher("index.jsp").forward(request, response);
	}
	
	
	@GET
	@Path("/{code}/getOpenid")
	@Produces(MediaType.APPLICATION_JSON)
	public DataBean getOpenid(@PathParam("code") String code){
		
		
		 String openid = Redis.c.get(Redis.K.CODE.to(code));
		 
		 return new DataBean(200, openid, "查询返回OpenId"); 
	}
	
	
	  @POST
		@Path("/submitWXOrderForm")
	    @Produces(MediaType.APPLICATION_JSON)
	    public DataBean submitWXOrderForm(JSONObject param){
	    	System.out.println("--------------------------------预支付回调-------------------------------------------------");
	    	
	    	WxPayData result = new WxPayData();
	    	try {
	    		
	    		
	    		if (!parse(param) || this.fields == null) {
					log.info("请求参数格式错误！");
					return new DataBean(400,new JSONObject(),"请求参数格式错误！");
				}
	    		
		    	//商户订单号
		    	String outTradeNo =  this.fields.getString("outTradeNo").trim(); //WxPayUtil.getOrderFormNumber();
		    			
		    	System.out.println(outTradeNo+"outTradeNo------------------------------------------------------");
		    	//商品价格
		    	int totalFee =  (int) (Double.parseDouble((this.fields.getString("totalFee").trim()))*100) ;
		    	System.out.println("totalFee----------------------->>"+totalFee);
		    	//客户端ip
		    	String createIp = request.getHeader("X-Real-IP");
		    	//用户标识
		    	String openId = this.fields.getString("openId").trim();
		    	//回调url
		    	//http://ts.chukeyunxing.com/ecar/r/pay/returnInfo
		    	String notifyUrl =   WeixinPayConfig.wxgzh_notify_url;
		    	
		    	String nonceStr = UUID.randomUUID().toString().replace("-", "").toUpperCase();
		    	String timeStamp = TimeUtil.getTimeStamp();
		    	
		    	String s= "订单号"+outTradeNo+"|openId"+openId+"|notifyUrl"+notifyUrl+"|totalFee"+totalFee;
		    	
			    //写出参数信息到服务器txt文件    
//			    writeFile(AlipayConfig.log_path+"1.txt",s,true);
		    	
		    	WxPayData wxReturnData = WxPayUtil.release(outTradeNo,totalFee,createIp,openId,notifyUrl,nonceStr);
		    	
		        result.setResult_code(wxReturnData.getResult_code());
		        result.setAppid(WxPayConstants.APPID);
		        result.setTimeStamp(timeStamp);
		        result.setNonce_str(nonceStr);
		        result.setPackageStr("prepay_id="+wxReturnData.getPrepay_id());
		        result.setSignType("MD5");
		    	
		      
		        
		    	//两者都为SUCCESS才能获取prepay_id
		    	if( wxReturnData.getResult_code().equals("SUCCESS") && wxReturnData.getReturn_code().equals("SUCCESS") ){
		    		//第二次签名,将微信返回的数据再进行签名
		            SortedMap<String,String> signMap = new TreeMap<String,String>();
		            signMap.put("appId", WxPayConstants.APPID);
		            signMap.put("timeStamp", timeStamp);
		            signMap.put("nonceStr", nonceStr);
		            signMap.put("package", "prepay_id="+wxReturnData.getPrepay_id());  //注：看清楚，值为：prepay_id=xxx,别直接放成了wxReturnData.getPrepay_id()
		            signMap.put("signType", "MD5");
		            String paySign = WechatUtils.buildRequestSign(signMap,WxPayConstants.KEY);//支付签名
		            log.info("paySign = {}",paySign);
		            result.setSign(paySign);
		    	}else{
		    		result.setResult_code("fail");
		    	}
	    	
	    	} catch (Exception e) {
	    		e.printStackTrace();
	    		System.out.println("生成预付订单异常!!!!!!!!!!!!!!!!");
	    	}
	    	System.out.println("result---------------------->>"+result.toString());
	        return new DataBean(500, result,"生成与支付订单！");
	    }
	    
	    @POST
		@Path("/returnInfo")
	    public void returnInfo(){
	    	
			try {
				InputStream is = request.getInputStream();
				String result = IOUtils.toString(is, "UTF-8");
				if("".equals(result)){
					response.getWriter().write("<xm><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[参数错误！]]></return_msg></xml>");
					return ;
				}
				log.info("接收的数据 xml:{}"+result.toString());
				WxPayData wxPayReq = WechatUtils.convertXmlToObject(WxPayData.class,result);
				log.info("接收的数据Object:{}"+wxPayReq.toString());
				String appid = wxPayReq.getAppid();
				String mch_id =wxPayReq.getMch_id();
				String nonce_str = wxPayReq.getNonce_str();
				//ordernum
				String out_trade_no = wxPayReq.getOut_trade_no();
				System.out.println("orderNo+______________________"+out_trade_no);
				int total_fee = wxPayReq.getTotal_fee();
				String trade_type = wxPayReq.getTrade_type();
				String openid =wxPayReq.getOpenid();
				String return_code = wxPayReq.getReturn_code();
				String result_code = wxPayReq.getResult_code();
	            String bank_type = wxPayReq.getBank_type();
	            Integer cash_fee = wxPayReq.getCash_fee();
				String fee_type = wxPayReq.getFee_type();
				String is_subscribe = wxPayReq.getIs_subscribe();
				String time_end = wxPayReq.getTime_end();
				String transaction_id = wxPayReq.getTransaction_id();
				String sign = wxPayReq.getSign();

				//签名验证
				SortedMap<String,String> parameters = new TreeMap<String,String>();
				parameters.put("appid",appid);
				parameters.put("mch_id",mch_id);
				parameters.put("nonce_str",nonce_str);
				parameters.put("out_trade_no",out_trade_no);
				parameters.put("total_fee",total_fee+"");
				parameters.put("trade_type",trade_type);
				parameters.put("openid",openid);
				parameters.put("return_code",return_code);
				parameters.put("result_code",result_code);
	            parameters.put("bank_type",bank_type);
	        	parameters.put("cash_fee",cash_fee+"");
				parameters.put("fee_type",fee_type);
				parameters.put("is_subscribe",is_subscribe);
				parameters.put("time_end",time_end);
				parameters.put("transaction_id",transaction_id);
				
				String sign2 = WechatUtils.buildRequestSign(parameters,WxPayConstants.KEY);//支付签名
				
				log.info("sign2 = {}",sign2);
				
				if(sign.equals(sign2)){//校验签名,确认预支付与回调 重要信息一致
					if(return_code.equals("SUCCESS") && result_code.equals("SUCCESS")){
						/**
						 *处理订单信息
						 */
						payService.createPayment(out_trade_no, total_fee, out_trade_no,time_end,Constants.TYPE_WECHATH5);
						log.info("--------------------------处理成功------------------------");
						//通知腾讯服务器
						response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
					}else{
						System.out.println("支付失败!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
						response.getWriter().write("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[交易失败]]></return_msg></xml>");
					}
				}else{
					response.getWriter().write("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名校验失败]]></return_msg></xml>");
				}
					
				response.getWriter().flush();
	            response.getWriter().close();
	            return ;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    }
	    
	    /** 
	     * 添加内容到指定文件 如果该文件不存在，则创建并添加内容 如果该文件已存在，则添加内容到已有内容最后 
	     * flag为true，则向现有文件中添加内容，否则覆盖原有内容 
	      
	     */ 
	    public static void writeFile(String filePathAndName, String fileContent,  
	            boolean flag) throws IOException {  
	        if (null == fileContent || fileContent.length() < 1)  
	            return;  
	        File file = new File(filePathAndName);  
	      
	        if (!file.exists()) {  
	            file.createNewFile();  
	        }  
	        FileOutputStream fos = new FileOutputStream(filePathAndName, flag);  
	        OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");  
	        osw.write(fileContent + "\r\n");  
	        osw.flush();  
	        osw.close();  
	    }   
}
